import Point from "./Point"
import Vec2 from "./Vec2"
// 约定 线的方向是 从 origin 朝向 target
export default class Line {
    readonly origin: Point
    readonly target: Point

    static create(startX: number, startY: number, endX: number, endY: number) {
        return new Line(new Point(startX, startY), new Point(endX, endY))
    }

    constructor(origin: Point, target: Point) {
        this.origin = origin
        this.target = target
    }

    /**
     * 获取线段方向
     */
    getDir() {
        return Vec2.fromValue(this.target.x - this.origin.x, this.target.y - this.origin.y)
    }

    /**
     * 获取和另外一条线的焦点
     */
    getIntersectPoint(target: Line) {
        const P1 = this.origin
        const P2 = target.origin

        // 计算方向向量
        const dir1 = this.getDir();
        const dir2 = target.getDir();

        // 计算行列式
        const det = dir1.x * dir2.y - dir1.y * dir2.x;

        // 检查是否平行
        if (det === 0) {
            return null; // 平行或重合
        }

        // 计算交点
        const d1 = (P2.x - P1.x) * dir2.y - (P2.y - P1.y) * dir2.x;
        const d2 = (P2.x - P1.x) * dir1.y - (P2.y - P1.y) * dir1.x;

        const t = d1 / det;
        const s = d2 / det;

        // 计算交点坐标
        const intersectionX = P1.x + t * dir1.x;
        const intersectionY = P1.y + t * dir1.y;

        return new Point(intersectionX, intersectionY)
    }

    /**
     * 从该线段截取子线段 起点是根据reverse判断
     * @param ratio 截取比例
     * @param reverse 是否置反,true则从target开始
     */
    getLine(ratio: number, reverse = false) {
        if (ratio < 0 || ratio > 1) {
            return reverse ? new Line(this.target, this.origin) : this
        }
        const vec2 = Vec2.fromValue(this.target.x - this.origin.x, this.target.y - this.origin.y).scale(ratio)
        return reverse ? Line.create(this.target.x, this.target.y, this.target.x - vec2.x, this.target.y - vec2.y) :
            Line.create(this.origin.x, this.origin.y, this.origin.x + vec2.x, this.origin.y + vec2.y)
    }

    /**
     * 截取线段
     * @param ratio 开始截取点
     * @param spliceLength 截取长度
     * @returns 
     */
    spliceLine(ratio: number, spliceLength: number) {
        if (ratio < 0 || ratio > 1) {
            return this
        }
        let end = ratio + spliceLength
        if (end < 0) {
            end = 0
        } else if (end > 1) {
            end = 1
        }
        const origin = this.getPoint(Math.min(ratio, end))
        const target = this.getPoint(Math.max(ratio, end))
        return new Line(origin, target)
    }

    /**
     * 置反线段,将origin和target对调
     */
    reverseLine() {
        return new Line(this.target, this.origin)
    }

    /**
     * 获取比例点,默认获取中心点
     * @param ratio 比例
     */
    getPoint(ratio: number = 0.5) {
        if (ratio < 0) {
            return Point.fromPoint(this.origin)
        }
        if (ratio > 1) {
            return Point.fromPoint(this.target)
        }
        const vec2 = Vec2.fromValue(this.target.x - this.origin.x, this.target.y - this.origin.y).scale(ratio)
        return new Point(this.origin.x + vec2.x, this.origin.y + vec2.y)
    }

    /**
     * 获取长度
     */
    getLength() {
        return Vec2.fromPoint(this.origin).distanceReal(this.target)
    }
}